package controller.ActionEvents;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import model.Account;
import model.Category;
import model.ModelClass;
import model.User;
import view.AdminPanel;
import view.CenterPanel;
import view.MainFrame;
import view.OptionPanes;
import view.user.Settings;
import view.user.Balance;
import view.user.Deposit;
import view.user.Leaderboard;
import view.user.Login;
import view.user.Statistics;
import view.user.Transfer;
import view.user.Withdrawal;
import controller.TableHandler;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;



/**
 * 
 * @author Christian
 *Class which receives ActionEvents from the view-classes.
 *Every ActionEvent must specify a ActionCommand, in order to be recognized by the unique if-statement.
 */

// Implements ActionListener from AWT package
public class ActionHandler implements ActionListener {
	private LoginClass loginClass;
	private AdminClass adminClass;
	private UserClass userClass;
	private TransactionClass transactionClass;
	
	// Access modifiers are set to protected, which allows subclasses to inherit.
	protected MainFrame frame;
	protected TableHandler mouseHandler;
	protected static ActionHandler singletonLogin = null; //Creates Singleton object. Is set to != null when users log in the first time
	protected static ActionHandler singletonAdminLogin = null;
	protected static ActionHandler singletonTransfer = null; //Creates Singleton object. Is set to != null when users log in the first time
	protected Settings settings;
	protected Balance balance;
	protected Deposit deposit;
	protected Withdrawal withdrawal;
	protected Leaderboard leaderboard;
	protected Login login;
	protected Statistics statistics;
	protected Transfer transfer;
	protected OptionPanes optionPanes;
	
	protected ModelClass modelClass;
	protected CenterPanel centerPanel;
	protected AdminPanel adminPanel;
	protected User currentUser;
	
	protected boolean falseLogin = false; //if falseLogin is false user isnt logged in yet.
	protected boolean falseAdminLogin = false; //if falselogin is false no administrator is yet logged in.
	/**
	 * @param frame is initialized by constructor as a parameter.
	 */
	public ActionHandler(MainFrame frame)
	{
		this.frame = frame;
		
	}
	/**
	 * Void method setObjects initializes objects, which are used as 'shortcuts' in the code.
	 */
	public void setObjects()
	{
		 		settings = frame.getCenterPanel().getAbout();
		 		balance = frame.getCenterPanel().getBalance();
				deposit = frame.getCenterPanel().getDeposit();
				withdrawal = frame.getCenterPanel().getWithdrawal();
				leaderboard = frame.getCenterPanel().getLeaderboard();
				login = frame.getLogin();
				statistics = frame.getCenterPanel().getStatistics();
				transfer = frame.getCenterPanel().getTransfer();
				optionPanes = frame.getOptionPanes();
				
				modelClass = frame.getModelClass();
				centerPanel = frame.getCenterPanel();
				adminPanel = frame.getAdminPanel();
				currentUser = frame.getModelClass().getCurrentUser();
	}
	
/**
 * @param event handles the incoming 'event requests', and performs the specified action.
 */
	@Override
	public void actionPerformed(ActionEvent event) 
	{
		System.out.println("actionPerformed is runned");
		//Sets the default skin, when user logs in.
//		frame.getSkinChanger().changeSkin(frame.getSkinChanger().getCurrentSkin());
		
		//setObjects() is invoked when user clicks performs an actionEvent.
		setObjects();
		
		// Creates new objects of subclasses.
		loginClass = new LoginClass(frame);
		adminClass = new AdminClass(frame);
		userClass = new UserClass(frame);
		transactionClass = new TransactionClass(frame);
		
	//Objects are locally initialized to shorten their usage in the class
		String actionCommand = event.getActionCommand();

		
		// Code seperation is used to seperator code snippets
		/*************************SHOW USER SHOW USER SHOW USER SHOW USER SHOW USER SHOW USER     **********************/
		/***************************************************************************************************************/	
		
		
		
		
		// Shows CardLayout balance
		if(actionCommand.equals("showBalance"))
		{
			centerPanel.show("BALANCE");
			refreshTables();
		}
	
		// Shows CardLayout withdrawal
		else if (actionCommand.equals("showWithdrawal"))
		{
			centerPanel.show("WITHDRAWAL");
			if(currentUser!=null){
				withdrawal.getComboBox().removeAllItems();
				for(Account account : modelClass.getUsersAccounts(modelClass.getCurrentUser())){
					
					withdrawal.getComboBox().addItem(""+account.getAccountName());
				}
				
				withdrawal.getComboBoxUsersCategories().removeAllItems();
				for(Category category : modelClass.getCategories())
				{
					if(category.getCategoryType().equals("withdrawal"))
					{
						withdrawal.getComboBoxUsersCategories().addItem(category.getCategoryName());
					}
				}
			}
		}
		
		// Shows CardLayout deposit
		else if (actionCommand.equals("showDeposit"))
		{
			userClass.setFieldDeposit(); // method initializes data in the JComponents
			centerPanel.show("DEPOSIT");
		}
		
		// Shows CardLayout leaderboard
		else if (actionCommand.equals("showLeaderboard"))
		{
			centerPanel.show("LEADERBOARD");
		}
		
		// Shows CardLayout transfer
		else if (actionCommand.equals("showTransfer"))
		{
			userClass.setFieldTransfer();
			centerPanel.show("TRANSFER");	
				
		}
		
		// Shows CardLayout settings
		else if (actionCommand.equals("showSettings"))
		{
			centerPanel.show("SETTINGS");
		}
		
		// Shows CardLayout statistics
		else if(actionCommand.equals("showStatistics"))
		{
			
			centerPanel.show("STATISTICS");
		}
		
		
		else if(actionCommand.equals("showCreateAccount"))
		{
			centerPanel.getCreateAccount().getListDeleteAccount().setEnabled(false);
			centerPanel.getCreateAccount().getRdbtnCreateAccount().setSelected(true);
			userClass.setFieldCreateAccount();
			centerPanel.show("CREATEACCOUNT");
		}
		
		else if (actionCommand.equals("showLogOff"))
		{
			frame.getSkinChanger().changeLoginSkin();
//			centerPanel.getLogin().setTxtUser(null);
//			centerPanel.getLogin().setPasswordField(null);
			frame.LoginFalse();
			falseLogin = false;	
		}
		
		//invoked when user changes to Goes Green skin.
		else if (actionCommand.equals("changeSkinGreen"))
		{
			frame.getSkinChanger().setCurrentSkin(2);
			frame.getSkinChanger().changeUserSkin();
			frame.getColorChanger().colorChange(Color.decode("#1cdd49"));
		}
		// Invoked when user changes to Classic skin.
		else if (actionCommand.equals("changeSkinClassic"))
		{
			frame.getSkinChanger().setCurrentSkin(1);
			frame.getSkinChanger().changeUserSkin();
			frame.getColorChanger().colorChange(Color.white);
		}
		/*************************SHOW ADMIN SHOW ADMIN SHOW ADMIN SHOW ADMIN SHOW ADMIN SHOW ADMIN **********************/
		/***************************************************************************************************************/	
		

		else if(actionCommand.equals("showAdminLoginScreen"))
		{
			frame.getSkinChanger().changeAdminSkin();
			frame.adminLoginTrue();
			adminPanel.show("ADMINLOGIN");
			login.getPasswordField().setText(null); //PasswordField is resetted.
		}
		
		// method adminLoginFalse() changes the layout visibility state.
		else if(actionCommand.equals("backFromAdmin"))
		{
			frame.adminLoginFalse();
		}
		
		else if(actionCommand.equals("backToAdminMenu"))
		{
			// sets the lblUsers' text
			adminPanel.getAdminMenu().getLblUsers().setText
			("Currently registred users: " + frame.getModelClass().getUsers().size());
			adminPanel.show("ADMINMENU");	
		}
		
		else if(actionCommand.equals("showAdminStatistics"))
		{
			adminClass.setFieldAdminStatistics();
			// sets the datamodel with a default 2D array.
			adminPanel.getAdminStatistics().setData(modelClass.getStatisticsData(currentUser.getID(), 1));
			
			// invokes the method repaint(), which redraws the whole graph on the JPanel.
			// This is necessary due to the above changed datamodel
			adminPanel.getAdminStatistics().repaint();
			adminPanel.show("ADMINSTATISTICS");
		}
		else if(actionCommand.equals("clearTransactions"))
		{
		modelClass.deleteAllTransactions();
		refreshTables();
		}
		
		
		else if(actionCommand.equals("showAdminLogOff"))
		{
			/* Sets the textfield and passwordfield to empty string and null,
			 so the users login info isnt stored, when the user logs out.
			 This is especially necessary if the application is used on a public computer, with many
			 users logging in and out.*/
			
			adminPanel.getAdminLogin().getTxtAdmin().setText("");
			adminPanel.getAdminLogin().getPasswordFieldAdmin().setText(null);
			adminPanel.show("ADMINLOGIN");	
		}
		
		
		/*************************NEW CATEGORIES NEW CATEGORIES NEW CATEGORIES NEW CATEGORIES    **********************/
		/***************************************************************************************************************/	
		else if(actionCommand.equals("newDepositCategorySubmit"))
		{
		transactionClass.addCategory("deposit");
		}
		
		else if(actionCommand.equals("newWithdrawalCategorySubmit"))
		{
		transactionClass.addCategory("withdrawal");
		}
		/*************************WITHDRAWAL WITHDRAWAL WITHDRAWAL WITHDRAWAL WITHDRAWAL WITHDRAWAL **********************/
		/***************************************************************************************************************/	
		else if(actionCommand.equals("withdrawalSUBMIT"))
		{
		transactionClass.withdrawalSubmit();
		}
		
		/*************************DEPOSIT DEPOSIT DEPOSIT DEPOSIT DEPOSIT DEPOSIT DEPOSIT DEPOSIT *************************/
		/***************************************************************************************************************/
		else if(actionCommand.equals("depositSUBMIT"))
		{
			transactionClass.depositSubmit();
		}
		
		/****************************************ABOUT ABOUT ABOUT ABOUT ABOUT ABOUT ABOUT   ***************************/
		/***************************************************************************************************************/
		else if(actionCommand.equals("SubmitPasswordChange"))
		{
			userClass.submitPasswordChange();
		}
		
		/************************************TRANSFER TRANSFER TRANSFER TRANSFER***************************************/
		/***************************************************************************************************************/
		
		else if(actionCommand.equals("transferSEARCH"))
		{
			transactionClass.transferSearch();
		}
		
		else if(actionCommand.equals("transferSUBMIT"))
		{
		transactionClass.transferSubmit();	
		}
		
		/**************************LOGIN LOGIN LOGIN LOGIN LOGIN LOGIN LOGIN LOGIN****************************************/
		/***************************************************************************************************************/
		
		/**
		 * User tries to login, which invokes following if-statement.
		 */
		else if (actionCommand.equals("showLogin"))
		{
			loginClass.showLogin();
			
			refreshTables();
			//Sets the default skin, when user logs in.
			
			
		} // end else if-statement
	
		/**************ADMIN ADMIN ADMIN ADMIN ADMIN ADMIN ADMIN ADMIN ADMIN ADMIN ******************************************/
		/***************************************************************************************************************/
		
		
		else if(actionCommand.equals("showAdminLogin"))
		{
			adminPanel.getAdminMenu().getLblUsers().setText
			("Currently registred users: "+frame.getModelClass().getUsers().size());
			
			frame.getSkinChanger().changeAdminSkin();
			
			loginClass.adminLogin();
			
		}
		
		else if(actionCommand.equals("showEditUser"))
		{
			adminPanel.show("ADMINEDITUSER");
			refreshTables();

		}
		
		else if(actionCommand.equals("showCreateUser"))
		{
			adminPanel.show("ADMINCREATEUSER");
		}
		
		else if(actionCommand.equals("showAdminStatistics"))
		{
			adminPanel.show("ADMINSTATISTICS");
		}
		
		else if(actionCommand.equals("showDeleteUser"))
		{
			adminClass.setFieldDeleteUser();
			adminPanel.show("ADMINDELETEUSER");
		}
	

		/*******************DELETE USER DELETE USER DELETE USER DELETE USER DELETE USER  ********************************/
		/***************************************************************************************************************/
		

		else if(actionCommand.equals("DeleteUser"))
		{
		adminClass.deleteUser();
		}
		

		/*******************CREATE USER CREATE USER CREATE USER CREATE USER CREATE USER ********************************/
		/***************************************************************************************************************/
		
		
		else if(actionCommand.equals("AddNewUser"))
		{
			adminClass.addNewUser();
		}
		/*******************************CREATE ACCOUNT CREATE ACCOUNT CREATE ACCOUNT **********************************/
		/***************************************************************************************************************/
		
		else if(actionCommand.equals("deleteAccount"))
		{
			// Enables the account field, forcing the user not to enter in field TxtNewAccountName
			centerPanel.getCreateAccount().getTxtNewAccountName().setEnabled(false);
			centerPanel.getCreateAccount().getLblNewAccountName().setEnabled(false);
			centerPanel.getCreateAccount().getListDeleteAccount().setEnabled(true);
			System.out.println("deleteAccount enabled");
		}
		
		else if(actionCommand.equals("addAccount"))
		{
			centerPanel.getCreateAccount().getTxtNewAccountName().setEnabled(true);
			centerPanel.getCreateAccount().getListDeleteAccount().setEnabled(false);
			System.out.println("addAccount enabled");
		}
		
		else if(actionCommand.equals("submitAccountChange"))
		{
			if(centerPanel.getCreateAccount().getTxtNewAccountName().isEnabled())
			{
				userClass.editAccount(false);
			}
			else if(centerPanel.getCreateAccount().getListDeleteAccount().isEnabled())
			{
				userClass.editAccount(true);
			}
		}
		/************************ ADMIN STATISTICS ADMIN STATISTICS ADMIN STATISTICS ADMIN STATISTICS ******************/
		/***************************************************************************************************************/
			
		else if(actionCommand.equals("submitAdminStatisticsChange"))
		{
			System.out.println("submit Statistics change");
			adminClass.setGraph();
		}
		
		else if(actionCommand.equals("setGraphSpecificUsersAccount"))
		{
			adminPanel.getAdminStatistics().getListUsers().setEnabled(true);	
		}
		else if(actionCommand.equals("setGraphUsersPasswordLength"))
		{
			adminPanel.getAdminStatistics().getListUsers().setEnabled(false);
		}
		else if(actionCommand.equals("setGraphAllAccountBalances"))
		{
			adminPanel.getAdminStatistics().getListUsers().setEnabled(false);	
		}
		else if(actionCommand.equals("setGraphYourOwnTransactions"))
		{
			adminPanel.getAdminStatistics().getListUsers().setEnabled(false);
		}
		
	} // end ActionPerformed method
	
	/**
	 * Refreshes JComponents which are affiliated to the current user.
	 */
	public void refreshObjects() 
	{
		// getID is shortened down to following integer.
		String ID = modelClass.getCurrentUser().getID();
		
		// double theBalance uses above int ID to create a variable of the balance, with argument ID
		double theBalance = modelClass.getTotalBalance(ID);
		
		// Creates a String variable of the current userName.
		String theUser = modelClass.getCurrentUser().getFullName();
		
		frame.getTotalAmount().getLblCurrentBalance().setText("Current Balance: "+ theBalance);
		
		frame.getTotalAmount().getLblCurrentUser().setText("Username: " + theUser);

		progressBar();	
	}
	
	/**
	 * Invokes when the user makes a data change, so the current data in the JTables
	 * datamodel is outdated, and therefore the dataVector has to be refreshed
	 */
	public void refreshTables()
	{
// Sets the Statistics JTable with new values			
		if(statistics.getTable() != null)
		{
		String[] columnHeadersStatistics = statistics.columnHeaders;
		statistics.getModel().setDataVector(modelClass.getStatisticsRows(),columnHeadersStatistics);
		}
// Sets the Balance JTable with new values		
		if(centerPanel.getBalance().getTable() != null)
		{
		String[] columnHeaderBalance = balance.columnHeaders;
		balance.getModel().setDataVector(modelClass.getAccountsRows(), columnHeaderBalance);
		}
// Sets the Leaderboard JTable with new values			
		if(leaderboard.getTable() != null)
		{
		String[] columnHeaderLeaderboard = centerPanel.getLeaderboard().columnHeaders;
		leaderboard.getModel().setDataVector(modelClass.getLeaderboard(), columnHeaderLeaderboard);
		leaderboard.getSorter().toggleSortOrder(2);
		leaderboard.getSorter().toggleSortOrder(2);
		leaderboard.getSorter().sort();
		}
		// Sets the EditUser JTable with new values	
		if(adminPanel.getAdminEditUser().getTable() != null)
		{
			System.out.println("updated leaderboard");
	String[] columnHeaderEditUser = adminPanel.getAdminEditUser().columnHeaders;
	adminPanel.getAdminEditUser().getModel().setDataVector(modelClass.getUsersRows(),columnHeaderEditUser);
		}
	}
	
	
	
	
	
	public void progressBar()
	{
		System.out.println("progressBar");
		// getID is shortened down to following integer.
		String ID = modelClass.getCurrentUser().getID();
		System.out.println(ID);
		JProgressBar progressBar = frame.getTotalAmount().getProgressBar();
				
		// double theBalance uses above int ID to create a variable of the balance, with argument ID
		double theBalance = modelClass.getTotalBalance(ID);
			
		
			
	// Nested if-statement sets the users level
		if(theBalance >= 1000 && theBalance < 2000)
		{
			progressBar.setMinimum(1000);
			progressBar.setMaximum(2000);
			progressBar.setString("Level 2");
		}
		
		else if(theBalance >= 2000 && theBalance < 3000)
		{
			progressBar.setMinimum(2000);
			progressBar.setMaximum(3000);
			progressBar.setString("Level 3");
		}
		
		else if(theBalance >= 3000 && theBalance < 4000)
		{
			progressBar.setMinimum(3000);
			progressBar.setMaximum(4000);
			progressBar.setString("Level 4");
		}
		else if(theBalance >= 4000 && theBalance < 5000)
		{
			progressBar.setMinimum(4000);
			progressBar.setMaximum(5000);
			progressBar.setString("Level 5");
		}
		
		else if(theBalance >= 5000 && theBalance < 10000)
		{
			progressBar.setMinimum(5000);
			progressBar.setMaximum(10000);
			progressBar.setString("Level 6");
		}
		else if(theBalance >= 10000 && theBalance < 15000)
		{
			progressBar.setMinimum(10000);
			progressBar.setMaximum(15000);
			progressBar.setString("Level 7");
		}
		else if(theBalance >= 15000 && theBalance < 20000)
		{
			progressBar.setMinimum(15000);
			progressBar.setMaximum(20000);
			progressBar.setString("Level 8");
		}
		else if(theBalance >= 20000 && theBalance < 30000)
		{
			progressBar.setMinimum(20000);
			progressBar.setMaximum(30000);
			progressBar.setString("Level 9");
		}
		else if(theBalance >= 30000)
		{
			progressBar.setMinimum(30000);
			progressBar.setMaximum(50000);
			progressBar.setString("Level 10");
		}
		progressBar.setValue((int) theBalance);
	}
	/**
	 * @return the frame
	 */
	public MainFrame getFrame() {
		return frame;
	}

	/**
	 * @param frame the frame to set
	 */
	public void setFrame(MainFrame frame) {
		this.frame = frame;
	}
	/**
	 * @return the loginClass
	 */
	public LoginClass getLoginClass() {
		return loginClass;
	}
}

/*
 * When using this program, you acknowledge that this isnt applicate for use in nuclear facilities, nor to launch  space rocket.
 */
